package com.github.icloudpay.pay.core.service.pay.wechat.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.lang.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.github.icloudpay.pay.core.feign.PayChannelConfigFeign;
import com.github.icloudpay.pay.core.inter.QueryPayStatusService;
import com.github.icloudpay.pay.core.service.pay.wechat.domain.QueryOrderElement;
import com.github.wxiaoqi.security.common.admin.pay.request.QueryPayStatusRequest;
import com.github.wxiaoqi.security.common.admin.pay.response.QueryPayStatusResponse;
import com.github.wxiaoqi.security.common.msg.ResponseCode;
import com.github.wxiaoqi.security.common.util.Utils;

/**
 * 微信订单状态查询
 * @author hexufeng
 *
 */
@Service("wechatPayQueryStatusService")
public class WechatPayQueryStatusService implements QueryPayStatusService{

	private static final Logger logger = (Logger) LoggerFactory.getLogger(WechatPayQueryStatusService.class);
	
	@Autowired
	private PayChannelConfigFeign payChannelConfigFeign;
	@Autowired
	private WechatSignatureService wechatSignatureService;

	@Override
	public QueryPayStatusResponse queryPayStatus(QueryPayStatusRequest request) {
		
		logger.info("****************调用微信订单状态查询接口开始*******************");

		QueryPayStatusResponse queryPayStatusResponse = new QueryPayStatusResponse();

		Map<String, Object> reqMap = new HashMap<String, Object>();
    	reqMap.put("platformId", request.getPlatformId());
    	reqMap.put("merchantId", request.getMerId());
    	reqMap.put("payChannelNo", request.getPayChannelNo());
		Map<String, Object> respMap = payChannelConfigFeign.query(reqMap);
        if(!(boolean) respMap.get("success")){
			queryPayStatusResponse.setSuccess(false);
			queryPayStatusResponse.setCode(ResponseCode.PAYCHANNEL_CONFIGURATION_NOTEXIST.getCode());
			queryPayStatusResponse.setMsg(ResponseCode.PAYCHANNEL_CONFIGURATION_NOTEXIST.getMessage());
			return queryPayStatusResponse;
		}
        
        @SuppressWarnings("unchecked")
		Map<String, Object> configMap = (Map<String, Object>)respMap.get("payChannelConfigInfo");
        
		String nonce_str=ObjectUtils.toString((new Random().nextInt() * (99999 - 10000 + 1)) + 10000);

		//根据获取的参数拼装XML信息
		QueryOrderElement reqElement = new QueryOrderElement();;
		reqElement.setAppid((String)configMap.get("OutMerAccount"));
		reqElement.setMch_id((String)configMap.get("outMerNo"));
		reqElement.setNonce_str(nonce_str);
		reqElement.setOut_trade_no(request.getOrderId());
		try {
			reqElement.setSign(wechatSignatureService.sign(reqElement, configMap));
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		String xmlStr = null;
		try {
			xmlStr = reqData2Xml(reqElement);
		} catch (JAXBException e) {
			logger.error("解析微信返回数据失败",e);
			queryPayStatusResponse.setSuccess(false);
			queryPayStatusResponse.setCode(ResponseCode.WECHAT_RESOLVE_FAIL.getCode());
			queryPayStatusResponse.setMsg(ResponseCode.WECHAT_RESOLVE_FAIL.getMessage());
			return queryPayStatusResponse;
		} 

		//       调用查询订单接口
		String queryUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; 
		HttpClient client=new HttpClient();
		PostMethod post=new PostMethod(queryUrl);
		try {  
			RequestEntity entity = new StringRequestEntity(xmlStr, "text/xml",  
					"UTF-8");  
			post.setRequestEntity(entity);  
			client.executeMethod(post);   
			int code = post.getStatusCode();  
			if (code == HttpStatus.SC_OK){ 
				String info = new String(post.getResponseBody(),"UTF-8");  
				String status = receiveResult(info,configMap).get("trade_status");
				logger.info("发送成功，返回的结果：", status);
				System.out.println(status);
				if(status!=null&&!"".equals(status)){
					if("SUCCESS".equals(status)){
						queryPayStatusResponse.setOrderAmt(new BigDecimal(receiveResult(info,configMap).get("orderAmt")));
						queryPayStatusResponse.setPayStatus(true);
						queryPayStatusResponse.setRemoteTxJournalNo(receiveResult(info,configMap).get("transaction_id"));
					}else if("USERPAYING".equals(status)){
						queryPayStatusResponse.setPayStatusStr("USERPAYING");
					}else{
						queryPayStatusResponse.setPayStatus(false);
					}
				}
				queryPayStatusResponse.setSuccess(true);
				queryPayStatusResponse.setCode(ResponseCode.OK.getCode());
				queryPayStatusResponse.setMsg(ResponseCode.OK.getMessage());
				return queryPayStatusResponse;
			}else{
				logger.error("发送数据失败");
				queryPayStatusResponse.setSuccess(false);
				queryPayStatusResponse.setCode(ResponseCode.SEND_DATA_FAIL.getCode());
				queryPayStatusResponse.setMsg(ResponseCode.SEND_DATA_FAIL.getMessage());
				return queryPayStatusResponse;
			}

		} catch (Exception ex) {  
			logger.error("返回失败",ex);
			ex.printStackTrace();  
		} finally {  
			post.releaseConnection();  
		}  
		return null;
	}

	/**
	 * 将请球参数转为Xml格式
	 * @throws JAXBException 
	 * @throws ParserConfigurationException 
	 */
	private String reqData2Xml(QueryOrderElement reqElement) throws JAXBException{
		JAXBContext context = JAXBContext.newInstance(QueryOrderElement.class);

		Marshaller marshaller = context.createMarshaller();
		marshaller.setProperty(Marshaller.JAXB_ENCODING,"UTF-8");//编码格式
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);//是否格式化生成的xml串
		marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);//是否省略xml头信息（<?xml version="1.0" encoding="gb2312" standalone="yes"?>）

		ByteArrayOutputStream outputstream = new ByteArrayOutputStream();

		StreamResult result = new StreamResult(outputstream);

		marshaller.marshal(reqElement, result);

		byte[] body = outputstream.toByteArray();

		return new String(body,Charset.forName("UTF-8"));
	}

	private Map<String,String> receiveResult(String info,Map<String, Object> configMap) throws ParserConfigurationException, SAXException, IOException{

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		InputStream is =  getStringStream(info);
		Document document = builder.parse(is);

		//获取到document里面的全部结点
		NodeList allNodes = document.getFirstChild().getChildNodes();
		Node node;
		Map<String, String> paramMap = new HashMap<String, String>();
		int i=0;
		while (i < allNodes.getLength()) {
			node = allNodes.item(i);
			if(node instanceof Element){
				paramMap.put(node.getNodeName(),node.getTextContent());
			}
			i++;
		}
		Map<String,String> returnMap=new HashMap<String, String>();
		String trade_status=(String)paramMap.get("trade_state");
		String orderAmt = ObjectUtils.toString(Utils.changeToYuan(paramMap.get("total_fee"))) ;

		returnMap.put("trade_status", trade_status);
		returnMap.put("orderAmt", orderAmt);
		return returnMap;

	}

	private  InputStream getStringStream(String sInputString) throws UnsupportedEncodingException {
		ByteArrayInputStream tInputStringStream = null;
		if (sInputString != null && !sInputString.trim().equals("")) {
			tInputStringStream = new ByteArrayInputStream(sInputString.getBytes("UTF-8"));
		}
		return tInputStringStream;
	}

}
